package com.lyy.component;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.nacos.shaded.com.google.protobuf.ServiceException;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

import java.util.Arrays;

/**
 * @author Liangyaoyun
 */
@Component
@Aspect
@Slf4j
public class ServiceAspect {

    @SneakyThrows
    @Around("execution(public * com.lyy.service.impl.*.*(..))")
    public Object aroundAdvice(ProceedingJoinPoint pjp) {

        // 获取方法参数
        Object[] args = pjp.getArgs();

        // 获取类名: 截取最后一个点和最后一个@之间的内容
        String className = pjp.getTarget().toString();
        int lastPoint = className.lastIndexOf(".") + 1;
        int lastAt = className.lastIndexOf("@");
        className = className.substring(lastPoint, lastAt);

        // 获取方法名
        String methodName = pjp.getSignature().getName();

        // 前置通知: 记录日志
        log.info("进入业务方法 {}.{}()，参数: {}", className, methodName, Arrays.toString(args));

        // 前置通知: 检查参数中是否存在空值
        if (ObjectUtil.hasNull(args)) {
            String msg = "业务方法 " + className + "." + methodName + "() 中存在null值参数";
            throw new ServiceException(msg);
        }

        // 调用目标方法
        Object returnValue = pjp.proceed(args);

        // 后置通知: 记录日志
        log.info("离开业务方法 {}.{}()，结果: {}", className, methodName, returnValue);

        // 返回目标方法的返回值
        return returnValue;
    }
}
